import java.awt.*;
import java.util.Vector;

public class CanvasUtente extends Canvas {
	
	private static final long serialVersionUID = 1L;

	/**
	 * Colore predefinito da impostare quando viene inizializzata un istanza della classe CanvasUtente
	 */
	
	private final Color defaultColor = Color.RED;
	
	/**
	 * Diametro del punto
	 */
	
	private int diametroPunto;
	
	/**
	 * Diametro della pallina
	 */
	
	private int diametroPalla;
	
	/**
	 * Vettore contenente i vari punti
	 */
	
	private Vector punti;
	
	/**
	 * Vettore contenente le forze
	 */
	
	private Vector forze;
	
	/**
	 * Vettore contenente le palline
	 */
	
	private Vector palline;
		
	/**
	 * Thread della classe
	 */
	
	private Thread t;
	
	/**
	 * Numero di molle che devono essere visualizzate
	 */
	
	private int oggetti;
	
	/**
	 * Costruttore della classe CanvasUtente; inizializza i vettori
	 *
	 */
	
	public CanvasUtente()
	{
		int fattore = 0;
		// numero predefinito di molle
		oggetti = 10;
		// dimensione Punto
		diametroPunto=10;
		//dimensiona Palla
		diametroPalla=10;
		forze = new Vector();
		palline = new Vector();
		punti = new Vector();
		for(int i = 0; i < oggetti; i++) {
			if(fattore > 0) fattore = -i*50;
			else fattore = i*10;
			Pallina pallina = new Pallina(diametroPalla);
			Punti punto = new Punti(80,80,diametroPunto);
			Forza forza = new Forza(pallina, punto);
			palline.add(pallina);
			punti.add(punto);
			forze.add(forza);
		}
	}
	
	/**
	 * Avvia i thread per tutti gli oggetti contenuti nei vettori 
	 *
	 */
	
	public void start() {
		for(int i = 0; i < 10; i++) {
			Forza forza = (Forza) forze.get(i);
			Pallina pallina = (Pallina) palline.get(i);
			Punti punto = (Punti) punti.get(i);
			pallina.setPointer(forza);
			
			pallina.startThread();
			punto.startThread();
			forza.startThread();	
		}
	}
	
	/**
	 * Ritorna il numero delle molle da visuallizzare
	 * @return Il numero delle molle
	 */
	
	public int getMolle() {
		return oggetti;
	}
	
	/**
	 * Setta la costante elastica per una sola molla o tutte
	 * @param value Valore della costante elastica
	 * @param molla Numero della molla da modificare
	 * @throws ArrayIndexOutOfBoundsException
	 */
	
	public void setK(double value, int molla) throws ArrayIndexOutOfBoundsException {
		if(molla == -1) {
			for(int i=0; i<oggetti; i++){
				Forza f = (Forza)forze.get(i);
				f.setKElastica(value);
				//System.out.println("Kelastica:" +value);
			}
		}
		else {
			Forza f = (Forza)forze.get(molla);
			f.setKElastica(value);
		}
	}
	
	/**
	 * Setta il coefficiente di attrito per una sola molla o tutte 
	 * @param value Valore del coefficiente di attrito
	 * @param molla Numero della molla da modificare
	 * @throws ArrayIndexOutOfBoundsException
	 */
	
	public void setAttrito(double value, int molla) throws ArrayIndexOutOfBoundsException {
		if(molla == -1) {
			for(int i=0; i< oggetti; i++){
				Pallina p = (Pallina)palline.get(i);
				p.setAttrito(value);
			}
		}
		else {
			Pallina p = (Pallina)palline.get(molla);
			p.setAttrito(value);
		}
	}
	
	/**
	 * Setta la massa per una sola molla o tutte
	 * @param value Valore della massa
	 * @param molla Numero della molla da modificare
	 * @throws ArrayIndexOutOfBoundsException
	 */
	
	public void setMassa(int value, int molla) throws ArrayIndexOutOfBoundsException {
		if(molla == -1) {
			for(int i=0; i< oggetti; i++){
				Pallina p = (Pallina)palline.get(i);
				p.setMassa(value);
			}
		}
		else {
			Pallina p = (Pallina)palline.get(molla);
			p.setMassa(value);
		}
	}
	
	/**
	 * Imposta il diametro per un punto o pallina o per tutte
	 * @param type b indica di modificare il diametro della pallina, p quello del punto
	 * @param value Valore del diametro
	 * @param molla Numero della molla da modificare
	 * @throws ArrayIndexOutOfBoundsException
	 */
	
	public void setDiametro(String type, int value, int molla) throws ArrayIndexOutOfBoundsException {
		if(molla == -1) {
			for(int i=0; i< oggetti; i++){
				if(type=="b"){ // se base
					Punti p = (Punti)punti.get(i);
					p.setDiametroPunto(value);
				}
				else if(type=="p"){ //se pallina
					Pallina p = (Pallina)palline.get(i);
					p.setDiametroPalla(value);
				}
				else // altrimenti
					; // non fare nulla
			}
		}
		else {
			if(type=="b"){ // se base
				Punti p = (Punti)punti.get(molla);
				p.setDiametroPunto(value);
			}
			else if(type=="p"){ //se pallina
				Pallina p = (Pallina)palline.get(molla);
				p.setDiametroPalla(value);
				//System.out.println("EVENTO!");
			}
		}
	}
	
	/**
	 * Imposta il colore per un punto o pallina o per tutte
	 * @param type b indica di modificare il colore della pallina, p quello del punto
	 * @param value Valore del colore in RGB
	 * @param molla Numero della molla da modificare
	 * @throws ArrayIndexOutOfBoundsException
	 */
	public void setColor(String type, int value, int molla) throws ArrayIndexOutOfBoundsException {
		if(molla == -1) {
			if(type=="b"){ // se base
				for(int i=0; i<oggetti; i++){
					Punti p = (Punti) punti.get(i);
					p.setRgbColor(value);
				}
			}
			else if(type=="p"){ //se pallina
				for(int i=0; i<oggetti; i++){
					Pallina p = (Pallina) palline.get(i);
					p.setRgbColor(value);
				}
			}
			else // altrimenti
				; // non fare nulla
		}
		else {
			if(type=="b"){ // se base
					Punti p = (Punti) punti.get(molla);
					p.setRgbColor(value);
			}
			else if(type=="p"){ //se pallina
					Pallina p = (Pallina) palline.get(molla);
					p.setRgbColor(value);
			}
		}
	}
	
	/**
	 * Aggiungi nuove molle o rimuovi quelle esistenti
	 * @param molle Numero delle molle da aggiungere o eliminare
	 */
	
	public void add(int molle) {
		
		int daAggiungere = molle - oggetti;
		if(molle == 0) {
			palline.clear();
			punti.clear();
			forze.clear();
			oggetti = 0;
		}
		else if(daAggiungere > 0) {
			for(int i = 0; i < daAggiungere; i++) {
				Pallina pallina = new Pallina(diametroPalla);
				Punti punto = new Punti(80,80,diametroPunto);
				Forza forza = new Forza(pallina, punto);
				palline.add(pallina);
				punti.add(punto);
				forze.add(forza);
			
				pallina.setPointer(forza);
				pallina.setColor(Color.RED);
				pallina.startThread();
				punto.startThread();
				forza.startThread();
				oggetti = molle;
			}
		}
		else {
			daAggiungere = -daAggiungere;
			for(int i = daAggiungere; i > 0 ; i--) {
				palline.remove(i);
				punti.remove(i);
				forze.remove(i);
				oggetti = molle;
			}
		}
			
	}
	
	/**
	 * Ritorna l'oggetto Forza alla posizione n-esiama del vettore 
	 * @param n Indice della forza
	 * @return L'oggetto Forza
	 * @throws ArrayIndexOutOfBoundsException
	 */
	
	public Forza getForza(int n) throws ArrayIndexOutOfBoundsException {
		return (Forza) forze.get(n);
	}
	
	/**
	 * Ritorna l'oggetto Pallina alla posizione n-esiama del vettore 
	 * @param n Indice della pallina
	 * @return L'oggetto Pallina
	 * @throws ArrayIndexOutOfBoundsException
	 */
	
	public Pallina getPallina(int n) throws ArrayIndexOutOfBoundsException {
		return (Pallina) palline.get(n);
	}
	
	/**
	 * Ritorna l'oggetto Punti alla posizione n-esiama del vettore 
	 * @param n Indice del punto
	 * @return L'oggetto Punti
	 * @throws ArrayIndexOutOfBoundsException
	 */
	
	public Punti getPunto(int n) throws ArrayIndexOutOfBoundsException {
		return (Punti) punti.get(n);
	}
	
	/**
	 * Disegna sullo schermo le linee che sono state tracciate
	 * @param g Oggetto Graphics su cui disegnare
	 */
	
	public void paint(Graphics g) {
		for(int i = 0; i < oggetti; i++) {
			Forza forza = (Forza) forze.get(i);
			Pallina pallina = (Pallina) palline.get(i);
			Punti punto = (Punti) punti.get(i);
			pallina.setPointer(forza);
			
			punto.disegna(g);
			pallina.disegna(g);
			forza.disegna(g);
		}
	}
	
	/**
	 * Ritorna il diametro del punto
	 * @return Il diametro
	 */
	
	public int getDiametroPunto() {
		return diametroPunto;
	}
	
	/**
	 * Imposta il diametro del punto
	 * @param _diametroPunto Il diametro
	 */
	
	public void setDiametroPunto(int _diametroPunto) {
		diametroPunto = _diametroPunto;
	}

	/**
	 * Ritorna il diametro della palla
	 * @return Il diametro
	 */
	
	public int getDiametroPalla() {
		return diametroPalla;
	}

	/**
	 * Imposta il diametro della palla
	 * @param _diametroPalla Il diametro
	 */
	
	public void setDiametroPalla(int _diametroPalla) {
		diametroPalla = _diametroPalla;
	}
	
}//class